﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.Profile;
using System.Web.Mvc;
using HQPad.Services;
using HQPad.DAL;
using HQPad.Models;
using HQPad.Helpers;

namespace HQPad.Controllers
{
    public class UserController : BaseController
    {
        public ActionResult Index()
        {
            // Get all user accounts.
            MembershipUserCollection userList = Membership.GetAllUsers();

            MembershipUser[] users = new MembershipUser[userList.Count];

            userList.CopyTo(users, 0);

            IEnumerable<UserModel> orderedList = 
                (from u in users
                 orderby u.UserName
                 select new UserModel {
                     User = u,
                     IsAdmin = Roles.IsUserInRole(u.UserName, "Admin")
                 });

            //users.OrderBy(u => u.UserName);


            return View(orderedList);
        }

        public ActionResult Edit(string userName)
        {
            MembershipUser user = Membership.GetUser(userName);

            if (user == null)
                throw new ApplicationException(string.Format("No memebership user with name {0} found.", userName));

            UserModel model = new UserModel() { 
                User = user,
                IsAdmin = Roles.IsUserInRole(userName, "Admin")
            };

            return View(model);
        }

        [HttpPost]
        public ActionResult Edit(string userName, FormCollection form)
        {
            MembershipUser user = Membership.GetUser(userName);

            if (user == null)
                throw new ApplicationException(string.Format("No memebership user with name {0} found.", userName));

            UserModel model = new UserModel()
            {
                User = user,
                IsAdmin = Roles.IsUserInRole(userName, "Admin")
            };

            bool enabled = form["enabled"].Contains("true");
            bool lockedOut = form["lockedOut"].Contains("true");

            string email = form["email"];

            if (string.IsNullOrEmpty(email))
            {
                ModelState.AddModelError("email", "Invalid email address");
                return View(model);
            }

            // update user.
            user.IsApproved = enabled;
            //user.IsLockedOut = lockedOut;
            user.Email = email;

            Membership.UpdateUser(user);

            // unlock is necessary.
            if (user.IsLockedOut && lockedOut == false)
                user.UnlockUser();
            
            return RedirectToAction("Index");
        }

        public ActionResult ChangePassword(string userName)
        {
            MembershipUser user = Membership.GetUser(userName);

            if (user == null)
                throw new ApplicationException(string.Format("No membership user with name {0} found.", userName));

            UserModel model = new UserModel()
            {
                User = user,
                IsAdmin = Roles.IsUserInRole(userName, "Admin")
            };

            return View(model);
        }

        [HttpPost]
        public ActionResult ChangePassword(string userName, FormCollection form)
        {
            MembershipUser user = Membership.GetUser(userName);

            if (user == null)
                throw new ApplicationException(string.Format("No membership user with name {0} found.", userName));

            UserModel model = new UserModel()
            {
                User = user,
                IsAdmin = Roles.IsUserInRole(userName, "Admin")
            };

            string newPassword = form["password"];

            if (string.IsNullOrEmpty(newPassword) || Membership.MinRequiredPasswordLength > newPassword.Length || !AuthenticationHelper.CheckPasswordForNonAlpha(newPassword))
            {
                ModelState.AddModelError("password", string.Format("Invalid password. Must be of at least {0} characters in length and have at least one non alphanumeric character.", Membership.MinRequiredPasswordLength));
                return View(model);
            }

            user.ChangePassword(user.ResetPassword(), newPassword);

            return View(model);
        }


        public ActionResult Characters(string userName)
        {
            IUnitOfWork context = new CharacterContext();
            ICharacterService service = new CharacterService(context);

            var characters = service.ListCharacters(userName);

            List<CharacterViewModel> characterList = new List<CharacterViewModel>();

            foreach (var character in characters)
            {
                CharacterRulesHelper helper = new CharacterRulesHelper(context, character.Xml);

                CharacterViewModel characterModel = new CharacterViewModel() { 
                    Name = helper.GetName(),
                    Class = helper.Class(),
                    Race = helper.Race(),
                    Rank = helper.Rank(),
                    Slug = character.Slug
                };

                characterList.Add(characterModel);
            }

            CharacterListViewModel model = new CharacterListViewModel() {
                Characters = characterList,
                UserName = userName
            };

            return View(model);
        }

        public ActionResult CopyToScratchPad(string slug, string userName)
        {
            IUnitOfWork context = new CharacterContext();
            ICharacterService service = new CharacterService(context);

            Character character = service.ListCharacters(userName).Where(a => a.Slug == slug).FirstOrDefault();

            if (character == null)
                return RedirectToAction("Index");

            ScratchPad clone = service.CopyCharacterToScratchPad(character.CharacterID, AuthenticationHelper.GetCurrentSessionId(Request));
            clone.UserName = AuthenticationHelper.GetCurrentUserName(HttpContext);
            clone.CharacterID = null;
            context.Save();

            return RedirectToAction("Index", "Character", new { name = character.Slug });
        }

        public ActionResult Settings()
        {
            //BuildPageTitle("Your settings");

            var profile = ProfileBase.Create(AuthenticationHelper.GetCurrentUserName(HttpContext));

            var model = new SettingsModel()
            {
                ShowAllSkills = (profile.GetPropertyValue("ShowAllGuildSkills") == null) ? true : Convert.ToBoolean(profile.GetPropertyValue("ShowAllGuildSkills"))
            };

            return View(model);
        }

        #region UpdateRecord
        /// <summary>
        /// Service method to update an adventure record.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public ActionResult UpdateSettings()
        {
            string showAllSkillsValue = Request.QueryString["showAllSkills"];
            bool showAllSkills = string.IsNullOrEmpty(showAllSkillsValue) || showAllSkillsValue.Contains("true");
            
            try
            {
                var profile = ProfileBase.Create(AuthenticationHelper.GetCurrentUserName(HttpContext));

                profile.SetPropertyValue("ShowAllGuildSkills", showAllSkills);
                profile.Save();
            }
            catch (Exception exception)
            {
                Response.StatusCode = 500;
                return PartialView("Message", string.Format("A system error occured. {0}", exception.Message));
            }

            return PartialView("Message", "User settings updated.");
        }
        #endregion
    }




    public class UserModel
    {
        public MembershipUser User { get; set; }
        public bool IsAdmin { get; set; }
    }

    public class SettingsModel
    {
        public bool ShowAllSkills { get; set; }
    }
}